home *** CD-ROM | disk | FTP | other *** search
- /*
-
- garbage collection, makePerm, and s_ memory allocation shells,
-
- for GCOOPE Version 1.0
-
- by Brian Lee Price
-
- Released as Public Domain July, 1994.
-
- */
-
- #include <alloc.h>
-
- #define __GARBAGE__
-
- #include "gcstruct.h"
-
-
- /* garbage collection static variables */
-
- static int ErrMem=0;
- static int Killed=0;
- static int curNdx=0;
- static int ageDcr=(int)MINDCRVAL;
- static int shftVal=MAXSHIFTVAL;
- static long timeVal=TIMVAL;
-
- /* round-robin routine with adaptive features */
- /*
- FOR KERNEL USE ONLY.
-
- This routine has two basic modes of operation, normally it
- only examines a few objects each call and the age decrement value
- is (usually) low. However in this basic mode, it is adaptive.
- A time out of timeVal will slow down the routine, while an internal
- out of memory error will speed up the routine. In this mode, the
- collector will ignore any objects which are not of the current
- process ID.
- The second mode of operation goes into effect on an out of
- memory condition. In this mode, it examines the maximum set number
- of objects, decrementing the age by the maximum amount, and ignores
- only a process ID of PERM_PROC_ID.
- */
-
- static void garbage(void)
- {
- register int x;
- register int locDcr;
- int oldDcr;
- int oldShft;
- objectEntry * objEnt;
-
- if(ErrMem)
- { /* on mem err, save norm parms, goto max vals */
- oldDcr=ageDcr;
- ageDcr=(int)MAXDCRVAL;
- oldShft=shftVal;
- shftVal=MINSHIFTVAL;
- }
- else if(--timeVal<=0) /* otherwise check for timer time out */
- {
- timeVal=TIMVAL;
- ageDcr-=ageDcr>>2; /* reduce DCR by 25% */
- if(ageDcr<MINDCRVAL)
- { /* if DCR bottomed out, check less often */
- ageDcr=(int)(MINDCRVAL*3)/2;
- shftVal+=(shftVal<(MAXSHIFTVAL))?1:0;
- }
- }
- x=(objList.maxElems)>>shftVal;
- x=(x<=0)?1:x;
- if(NULL==(objEnt=objList.listPtr)) return;
-
- for(locDcr=ageDcr;x>0;x--,curNdx++)
- {
- if(curNdx>=objList.maxElems) curNdx=0;
- if(NULL==(objEnt[curNdx].objDef)) continue;
- else if((curProcID!=objEnt[curNdx].procID && !ErrMem)
- || (objEnt[curNdx].procID==PERM_PROC_ID)) continue;
- else if(objEnt[curNdx].lastAcc>locDcr) objEnt[curNdx].lastAcc-=locDcr;
- else
- {
- g(Kill)((object) curNdx);
- Killed=1;
- }
- }
- if(ErrMem) /* if in memory error mode reset to normal parms */
- {
- if(Killed)
- {
- ageDcr=oldDcr+(oldDcr>>1); /* increase norm DCR by 50% */
- shftVal=oldShft;
- if(ageDcr>MAXDCRVAL)
- { /* if DCR MAXED, check more often */
- ageDcr=(int)MAXDCRVAL/2;
- shftVal-=(shftVal>MINSHIFTVAL)?1:0;
- }
- }
- else
- {
- ageDcr=oldDcr;
- shftVal=oldShft;
- }
- ErrMem=0;
- }
- }
-
-
- /*
- AVAILABLE FOR EXTERNAL USE.
-
- This routine makes an object permanent with respect to the garbage
- collector. After this call is made, g(Kill)(object,...) must be
- called in order to remove the object from memory.
- */
-
- stat makePerm(object instance)
- {
- objectEntry * objEnt;
-
- if(instance<0) return FUNCOKAY;
- if((NULL==(objEnt=getObject((tag) instance)))
- || (NULL==objEnt->objDef)) return FUNCFAIL;
- objEnt->procID=PERM_PROC_ID;
- return FUNCOKAY;
- }
-
- /*
- FOR KERNEL USE ONLY.
-
- This routine fakes a memory error if a list runs out of available
- elements. Thus the garbage collector will kill off some of the older
- instances to free up available slots.
- */
-
- void outOfElems(void)
- {
- int x;
-
- ErrMem=1;
- Killed=0;
- for(x=MAX_ERR_TRY;x>0 && !Killed;x--) garbage();
- if(!Killed) g(Err)(Object,Object,gcerrmsg[ERR_OUT_OF_MEM]);
- }
-
-
-
- /*
- AVAILABLE FOR EXTERNAL USE.
-
- This is the standard library calloc shell, note that it works
- directly with the garbage collector and as long as the default error
- routine aborts the program, it NEVER returns NULL.
- */
-
- void * s_calloc(unsigned nitems, unsigned size)
- {
- void * retVal;
-
- garbage();
- while(NULL==(retVal=calloc(nitems,size))) outOfElems();
- return retVal;
- }
-
- /*
- AVAILABLE FOR EXTERNAL USE.
-
- This routine is here mostly for completeness, however note
- that when upgrading to an aftermarker heap manager only the shell
- routines in this module need to be modified.
-
- */
-
- void s_free(void * block)
- {
- if(block!=NULL) free(block);
- }
-
-
- void * s_malloc(unsigned size)
- {
- void * retVal;
-
- garbage();
- while(NULL==(retVal=malloc(size))) outOfElems();
- return retVal;
- }
-
-
- /*
- AVAILABLE FOR EXTERNAL USE.
-
- See s_calloc and s_free for notes.
- */
-
- void * s_realloc(void * block, unsigned newSize)
- {
- void * retVal;
-
- garbage();
- while(NULL==(retVal=realloc(block,newSize))) outOfElems();
- return retVal;
- }
-
-